import React, { Component, createRef } from 'react'
// 导入请求模块
import { API } from '../../utils/api'
// 导入 NavBar 组件
import { NavBar, Toast } from 'antd-mobile'
// 导入 List 组件
import { List, AutoSizer } from 'react-virtualized'
// 导入样式
import './index.scss'
// 导入 utils 中，获取城市的方法
import { getCurrentCity, setCity } from '../../utils'

// 数据格式化的方法
// list: [{}, {}]
const formatCityData = list => {
  const cityList = {}

  // 1. 遍历list组件
  list.forEach(item => {
    // 2. 获取每一个城市首字母
    const first = item.short.slice(0, 1)
    // 3. 判断 citylist 是否有该分类
    if (cityList[first]) {
      // 4. 如果有，直接往该分类中 push 数据
      cityList[first].push(item)
    } else {
      // 5. 如果没有，就先创建一个数组，然后，把当前城市信息添加到数组中
      cityList[first] = [item]
    }
  })

  // 获取索引数据
  const cityIndex = Object.keys(cityList).sort()

  return {
    cityList,
    cityIndex
  }
}

// 封装处理字母索引的方法
const formatCityIndex = letter => {
  switch (letter) {
    case '#':
      return '当前定位'
    case 'hot':
      return '热门城市'
    default:
      return letter.toUpperCase()
  }
}

// 索引（A、B等）的高度
const TITLE_HEIGHT = 36
// 每个城市名称的高度
const NAME_HEIGHT = 52

// 有房源的城市
const HOUSE_CITY = ['北京', '上海', '广州', '深圳']

export default class CityList extends Component {
  constructor(props) {
    super(props)

    this.state = {
      cityList: {},
      cityIndex: [],
      // 指定右侧字母索引列表高亮的索引号
      activeIndex: 0
    }

    // 创建 ref 对象
    this.cifyListComponent = createRef()
  }

  async componentDidMount() {
    await this.getCityList()

    // 调用 measureAllRows，提前计算 List 中每一行的高度，实现 scrollToRow 的精度跳转
    // 注：调用这个方法的时候，需要保证 List 组件中已经有数据了！如果 List 组件中的数据为空，就导致调用该方法报错！
    // 解决：只要保证这个方法是在 获取到数据之后 调用的即可
    this.cifyListComponent.current.measureAllRows()
  }

  // 获取城市列表的方法
  async getCityList() {
    const { data: res } = await API.get('/area/city?level=1')
    const { cityList, cityIndex } = formatCityData(res.body)

    // 获取热门城市数据
    const { data: hotRes } = await API.get('/area/hot')
    // 将数据添加到 cityList 中
    cityList['hot'] = hotRes.body
    // 将索引添加到 cityIndex 中
    cityIndex.unshift('hot')

    // 获取当前定位城市
    const curCity = await getCurrentCity()
    /*
      1. 将当前定位城市数据添加到 cityList 中
      2. 将当前定位城市索引添加到 cityIndex 中
    */
    cityList['#'] = [curCity]
    cityIndex.unshift('#')

    this.setState({
      cityList,
      cityIndex
    })
  }

  changeCity({ label, value }) {
    if (HOUSE_CITY.includes(label)) {
      // 有，存储到本地存储中
      // localStorage.setItem('hkzf_city', JSON.stringify({ label, value }))
      setCity({ label, value })
      this.props.history.go(-1)
    } else {
      Toast.show({ content: '该城市暂无房源！', duration: 1000 })
    }
  }

  // 渲染每一行数据的渲染行数
  // 函数的返回值就表示最终渲染在页面中的内容
  // List 渲染每一行的方法
  rowRenderer = ({
    key, // Unique key within array of rows
    index, // 索引号
    style // 指定每一行的数据（必选）
  }) => {
    const { cityIndex, cityList } = this.state
    // 获取每一行的字母索引
    const letter = cityIndex[index]

    return (
      <div className="city" key={key} style={style}>
        <div className="title">{formatCityIndex(letter)}</div>
        {cityList[letter].map(item => (
          <div className="name" key={item.value} onClick={() => this.changeCity(item)}>
            {item.label}
          </div>
        ))}
      </div>
    )
  }

  // 创建动态计算每一行高度的方法
  getRowHeight = ({ index }) => {
    // 索引标题高度 + 城市数量 * 城市名称高度
    // TITLE_HEIGHT + cityList[cityIndex[index]].length * NAME_HEIGHT
    const { cityIndex, cityList } = this.state
    return TITLE_HEIGHT + cityList[cityIndex[index]].length * NAME_HEIGHT
  }

  // 渲染右侧索引的方法
  renderCityIndex() {
    // 获取到 cityIndex，并遍历实现渲染
    const { cityIndex, activeIndex } = this.state
    return cityIndex.map((item, index) => (
      <li key={item}>
        <span
          className={activeIndex === index ? 'index-active' : ''}
          onClick={() => {
            this.cifyListComponent.current.scrollToRow(index)
          }}
        >
          {item === 'hot' ? '热' : item.toUpperCase()}
        </span>
      </li>
    ))
  }

  // 用于获取 List 组件中渲染行的信息
  onRowsRendered = ({ startIndex }) => {
    if (this.state.activeIndex !== startIndex) {
      this.setState({
        activeIndex: startIndex
      })
    }
  }

  render() {
    return (
      <div className="citylist">
        {/* 导航栏 */}
        <NavBar onBack={() => this.props.history.go(-1)}>城市选择</NavBar>

        {/* 城市列表 */}
        <AutoSizer>
          {({ width, height }) => (
            <List
              ref={this.cifyListComponent}
              width={width}
              height={height}
              rowCount={this.state.cityIndex.length}
              rowHeight={this.getRowHeight}
              rowRenderer={this.rowRenderer}
              onRowsRendered={this.onRowsRendered}
              scrollToAlignment="start"
            />
          )}
        </AutoSizer>

        {/* 右侧索引列表 */}
        <ul className="city-index">{this.renderCityIndex()}</ul>
      </div>
    )
  }
}
